<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>svg笔记</title>
    <style>
        table {
            border-collapse: collapse;
        }
        table tr td {
            border: 1px solid #eee;
            padding: 3px 15px;
        }
    </style>
</head>
<body>
    <h3>svg笔记</h3>
    <ul>
        <li>使用XML描述的矢量文件</li>
        <li>W3C标准（1.1）（<a href="http://www.w3.org/TR/SVG11" target="_blank">http://www.w3.org/TR/SVG11</a>）</li>
        <li>浏览器支持情况（<a href="http://caniuse.com/#cats=svg" target="_blank">http://caniuse.com/#cats=svg</a>）
            <ul>
                <li>IE 9+</li>
                <li>Chrome 33.0+</li>
                <li>Firefox 28.0+</li>
                <li>Safari 7.0+</li>
            </ul>
        </li>
        <br>
        <li>使用方式
            <ul>
                <li>在浏览器中直接打开</li>
                <li>在HTML中使用<img>标签</li>
                <li>直接在HTML中使用SVG标签</li>
                <li>作为css背景</li>
            </ul>
        </li>
        <br>
        <li>基本图形和属性
            <ul>
                <li>基本图形
                    <ul>
                        <li>&lt;rect&gt;,&lt;circle&gt;,&lt;ellipse&gt;,&lt;line&gt;,&lt;polyline&gt;,&lt;polygon&gt;
                            <ul>
                                <li>&lt;rect&gt;矩形，x、y 定义左上角位置，width、height 定义宽高，rx、ry
                                    定义圆角（只定义了rx时，ry自动等于rx，只定义ry同样，只有两个分别定义才不一样）</li>
                                <li>示例：
                                    <svg width="100px" height="20px">
                                        <rect x="0" y="0" width="60px" height="20px" style="fill: red" rx="5"></rect>
                                    </svg>
                                </li>
                                <li>&lt;circle&gt;圆，cx、cy 定义圆心的位置、r 定义半径</li>
                                <li>示例：
                                    <svg width="100px" height="20px">
                                        <circle cx="10" cy="10" r="10" style="fill: red"></circle>
                                    </svg>
                                </li>
                                <li>&lt;ellipse&gt;椭圆，cx、cy 定义圆心的位置，rx，ry 定义x，y轴方向的半径</li>
                                <li>示例：
                                    <svg width="100px" height="20px">
                                        <ellipse cx="15" cy="10" rx="15" ry="10" style="fill: red"></ellipse>
                                    </svg>
                                </li>
                                <li>&lt;line&gt;直线，x1、y1、x2、y2 定义两点的位置</li>
                                <li>示例：
                                    <svg width="100px" height="20px">
                                        <line x1="0" y1="0" x2="60" y2="20" style="stroke: red"></line>
                                    </svg>
                                </li>
                                <li>&lt;polyline&gt;折线 points = "x1 y1 x2 y2 x3 y3..."定义多点的位置</li>
                                <li>示例：
                                    <svg width="100px" height="20px">
                                        <polyline points="0,0,20,20,40,0,60,20"
                                                  style="stroke: red;fill:#fff;"></polyline>
                                    </svg>
                                </li>
                                <li>&lt;polygon&gt;折线 points = "x1 y1 x2 y2  x3 y3..."定义多点的位置，最后一个点会自动和第一个点相连形成闭合的图形</li>
                                <li>示例：
                                    <svg width="100px" height="20px">
                                        <polygon points="0 0 20 20 40 0 100 20" style="stroke: red;fill:#ccc;"></polygon>
                                    </svg>
                                </li>
                            </ul>
                        </li>
                    </ul>
                </li>
                <li>基本属性
                    <ul>
                        <li>fill 填充颜色，stroke 描边颜色，stroke-width 描边粗细，transform 变换</li>
                    </ul>
                </li>
                <li>基本操作API
                    <ul>
                        <li>创建图形：document.createElementNS(ns,tagName)</li>
                        <li>添加图形：element.appendChild(childElement)</li>
                        <li>设置、获取属性：element.setAttribute(name,value)、elment.getAttribute(name)</li>
                    </ul>
                </li>
            </ul>
        </li>
        <br>
        <li>SVG的世界、视野、视窗
            <ul>
                <li>width，height - 控制视窗</li>
                <li>SVG代码 - 定义世界</li>
                <li>viewBox，preserveAspectRatio - 控制视野</li>
                <li> viewBox 属性接收四个参数值，包括： &lt;min-x&gt;, &lt;min-y&gt;, width  和  height 。<br> &lt;min-x&gt;  和  &lt;min-y&gt;  值决定viewBox的左上角， width 和 height 决定视窗的宽高。这里要注意视窗的宽高不一定和父 &lt;svg&gt; 元素的宽高一样。 &lt;width&gt; 和 &lt;height&gt; 值为负数是不合法的。值为 0 的话会禁止元素的渲染。</li>
                <li>preserveAspectRatio属性强制统一缩放比来保持图形的宽高比。
                    <ul>
                        <li>preserveAspectRatio的官方语法是:preserveAspectRatio = defer? &lt;align&gt;&lt;meetOrSlice&gt;</li>
                        <li> defer 声明是可选的，并且只有当你在 &lt;image&gt; 上添加 preserveAspectRatio 才被用到。用在任何其他元素上时它都会被忽略。</li>
                        <li> align 参数声明是否强制统一放缩，如果是，对齐方法会在 viewBox 的宽高比不符合viewport的宽高比的情况下生效。</li>
                        <li> 如果 align 值设为 none,例如：preserveAspectRatio = "none"，图形不再保持宽高比而会缩放来适应视窗</li>
                        <li> 其他所有 preserveAspectRatio 值都在保持viewBox的宽高比的情况下强制拉伸，并且指定在视窗内如何对齐viewBox。
                            <ul>
                                <li>xMinYMin <br>强制统一缩放 <br>视窗X轴的最小值对齐元素viewBox的&lt;min-x&gt;<br>视窗Y轴的最小值对齐元素viewBox的&lt;min-y&gt; <br>把这个类比为:backrgound-position: 0% 0%;</li>
                                <li>xMinYMid 把这个类比为 backrgound-position: 0% 50%;</li>
                                <li>xMinYMax 把这个类比为 backrgound-position: 0% 100%;</li>
                                <li>xMidYMin 把这个类比为 backrgound-position: 50% 0%;</li>
                                <li>xMidYMid 把这个类比为 backrgound-position: 50% 50%;</li>
                                <li>xMidYMax 把这个类比为 backrgound-position: 50% 100%;</li>
                                <li>xMaxYMin 把这个类比为 backrgound-position: 100% 0%;</li>
                                <li>xMaxYMid 把这个类比为 backrgound-position: 100% 50%;</li>
                                <li>xMaxYMax 把这个类比为 backrgound-position: 100% 100%;</li>
                            </ul>
                        </li>
                        <li> 最后一个属性， meetOrSlice 也是可选的，默认值为 meet 。这个属性声明整个 viewBox 在视窗中是否可见。如果是，它和 align 参数通过一个或多个空格分隔。例如：preserveAspectRatio = ""xMinYMin slice""</li>
                    </ul>
                </li>
            </ul>
        </li>
        <br>
        <li>svg中的图形分组
            <ul>
                <li>&lt;g&gt;标签来创建分组
                    <ul>示例：
                        <li>
                            <svg xmlns="http://www.w3.org/2000/svg">
                                <g stroke="green" fill="#ffffff" transform="rotate(20)">
                                    <rect x="0" y="0" width="100" height="30"></rect>
                                    <rect x="40" y="30" width="20" height="120"></rect>
                                </g>
                            </svg>
                        </li>
                    </ul>
                </li>
                <li>属性继承</li>
                <li>transform属性定义坐标变换</li>
                <li>可以嵌套使用</li>
            </ul>
        </li>
        <br>
        <li>四个坐标系
            <ul>
                <li>用户坐标系
                    <ul>
                        <li>世界的坐标系</li>
                    </ul>
                </li>
                <li>自身坐标系
                    <ul>
                        <li>每个图形元素或分组独立与生俱来</li>
                    </ul>
                </li>
                <li>前驱坐标系
                    <ul>
                        <li>父容器的坐标系</li>
                    </ul>
                </li>
                <li>参考坐标系
                    <ul>
                        <li>使用其他坐标系来考究自身的情况时使用</li>
                    </ul>
                </li>
            </ul>
        </li>
        <br>
        <li>线性变换
            <ul>
                <li>线性变换方程</li>
                <li>X' = aX + cY +e</li>
                <li>Y' = bX + dY +f</li>
                <br>
                <li>变换矩阵，记为M</li>
                <li style="position: relative">
                    <svg xmlns="http://www.w3.org/2000/svg">
                        <g stroke="green" fill="#ffffff" transform="translate(0,20)">
                            <polyline points="20,0,0,0,0,100,20,100" style="stroke: red;"></polyline>
                            <polyline points="80,0,100,0,100,100,80,100" style="stroke: red;"></polyline>
                        </g>
                    </svg>
                    <div style="    position: absolute;top: 5px;left: 20px;color: red;">
                        <p>a &nbsp; c &nbsp; e</p>
                        <p>b &nbsp; d &nbsp; f</p>
                        <p>0 &nbsp; 0 &nbsp; 1</p>
                    </div>
                </li>
                <br>
                <li>使用极坐标求变换矩阵(旋转)</li>
                <li style="position: relative">
                    <svg xmlns="http://www.w3.org/2000/svg">
                        <g stroke="green" fill="#ffffff" transform="translate(0,20)">
                            <polyline points="20,0,0,0,0,100,20,100" style="stroke: red;"></polyline>
                            <polyline points="180,0,200,0,200,100,180,100" style="stroke: red;"></polyline>
                        </g>
                    </svg>
                    <div style="    position: absolute;top: 5px;left: 20px;color: red;">
                        <p>cos(30°)&nbsp; -sin(30°)&nbsp; 0</p>
                        <p>sin(30°) &nbsp; cos(30°)&nbsp; 0</p>
                        <p>0 &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp;  &nbsp; &nbsp;  &nbsp;  &nbsp;0 &nbsp;  &nbsp; &nbsp;
                            &nbsp;1</p>
                    </div>
                </li>
                <br>
                <li>缩放（示例是x和y轴两倍的缩放）</li>
                <li style="position: relative">
                    <svg xmlns="http://www.w3.org/2000/svg">
                        <g stroke="green" fill="#ffffff" transform="translate(0,20)">
                            <polyline points="20,0,0,0,0,100,20,100" style="stroke: red;"></polyline>
                            <polyline points="80,0,100,0,100,100,80,100" style="stroke: red;"></polyline>
                        </g>
                    </svg>
                    <div style="    position: absolute;top: 5px;left: 20px;color: red;">
                        <p>2 &nbsp; 0 &nbsp; 0</p>
                        <p>0 &nbsp; 2 &nbsp; 0</p>
                        <p>0 &nbsp; 0 &nbsp; 1</p>
                    </div>
                </li>
                <br>
                <li>多个线性变换：后面的矩阵乘以前面</li>
            </ul>
        </li>
        <br>
        <li>transform属性
            <ul>
                <li>rotate(deg)</li>
                <li>translate(x,y)</li>
                <li>scale(sx,sy)</li>
                <li>matrix(a,b,c,d,e,f)</li>
            </ul>
        </li>
        <br>
        <li>RGB和hsl
            <ul>
                <li>RGB优势：显示器容易解析；劣势：不符合人类藐视颜色的习惯</li>
                <li>hsl三个分量分别表示颜色，饱和度和亮度，取值范围h：0--359，s、l：0--100</li>
            </ul>
        </li>
        <br>
        <li>渐变
            <ul>
                <li>线性渐变
                    <ul>
                        <li>&lt;linearGradient&gt;和&lt;stop&gt;</li>
                        <li>linearGradient默认的参数是gradientUnits="objectBoundingBox"
                            <svg xmlns="http://www.w3.org/2000/svg">
                                <defs>
                                    <linearGradient id="grad1" x1="0" y1="0" x2="1" y2="1">
                                        <stop offset="0" stop-color="#1497fc"></stop>
                                        <stop offset="0.5" stop-color="#a469be"></stop>
                                        <stop offset="1" stop-color="#ff8c00"></stop>
                                    </linearGradient>
                                </defs>
                                <rect x="0" y="0" fill="url(#grad1)" width="200" height="150"></rect>
                            </svg>
                        </li>
                        <li>linearGradient参数改变一个时gradientUnits="userSpaceOnUse",x2,y2也要做出调整（世界坐标）
                            <svg xmlns="http://www.w3.org/2000/svg">
                                <defs>
                                    <linearGradient id="grad1" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="100" y2="100">
                                        <stop offset="0" stop-color="#1497fc"></stop>
                                        <stop offset="0.5" stop-color="#a469be"></stop>
                                        <stop offset="1" stop-color="#ff8c00"></stop>
                                    </linearGradient>
                                </defs>
                                <rect x="0" y="0" fill="url(#grad1)" width="200" height="150"></rect>
                            </svg>
                        </li>
                    </ul>
                </li>
                <br>
                <li>径向渐变
                    <ul>
                        <li>&lt;radialGradient&gt;和&lt;stop&gt;</li>
                        <li>fx,fy表示焦点的位置，r表示圆心,不同时存在
                            <svg xmlns="http://www.w3.org/2000/svg">
                                <defs>
                                    <radialGradient id="grad2" cx="0.5" cy="0.5" fx="0.6" fy="0.3">
                                        <stop offset="0" stop-color="#1497fc"></stop>
                                        <stop offset="0.5" stop-color="#a469be"></stop>
                                        <stop offset="1" stop-color="#ff8c00"></stop>
                                    </radialGradient>
                                </defs>
                                <rect x="0" y="0" fill="url(#grad2)" width="200" height="150"></rect>
                            </svg>
                        </li>
                    </ul>
                </li>
            </ul>
        </li>
        <br>
        <li>笔刷
            <ul>
                <li>绘制纹理，&lt;pattern&gt;标签，patternUnits和patternContentUnits</li>
                <li>pattern里面定义的宽高是基于百分比定义的，<br>但是加入：patternUnits="userSpaceOnUse"参数时，宽高则是基于世界坐标 <br>
                    加入patternContentUnits="ObjectBoundingBox"时，pattern的子元素表示基于百分比定义的
                </li>
                <li>
                    <svg xmlns="http://www.w3.org/2000/svg">
                        <defs>
                            <pattern id="p1" x="0" y="0" width="0.2" height="0.2">
                                <circle cx="10" cy="10" r="5" fill="red"></circle>
                                <polygon points="30,10,60,50,0,50" fill="green"></polygon>
                            </pattern>
                        </defs>
                        <rect x="0" y="0" fill="url(#p1)" stroke="blue" width="300" height="150"></rect>
                    </svg>
                </li>
            </ul>
        </li>
        <br>
        <li>path
            <ul>
                <li>规范：<a href="http://www.w3.org/TR/SVG11/paths.html" target="_blank"></a>http://www.w3.org/TR/SVG11/paths.html</li>
                <li>强大的绘图工具，由命令及其参数数组组成的字符串</li>
                <li>&lt;path d="M0,0L10,20C30-10,40,20,100,100" stroke="red"&gt;
                    L表示命令，后面的数字为参数，由逗号隔开，下一个参数是负数除外，也能由空格隔开</li>
            </ul>
            <ul>
                <li>path命令汇总</li>
                <li>
                    <table>
                        <tr>
                            <td>命令</td>
                            <td>含义</td>
                        </tr>
                        <tr>
                            <td>M/m(x,y)+</td>
                            <td>移动当前位置</td>
                        </tr>
                        <tr>
                            <td>L/l(x,y)+</td>
                            <td>从当前位置绘制线段到指定位置</td>
                        </tr>
                        <tr>
                            <td>H/h(x)+</td>
                            <td>从当前位置绘制水平线到达指定的x坐标</td>
                        </tr>
                        <tr>
                            <td>V/v(y)+</td>
                            <td>从当前位置绘制竖直线到达指定的y坐标</td>
                        </tr>
                        <tr>
                            <td>Z/z</td>
                            <td>闭合当前路径</td>
                        </tr>
                        <tr>
                            <td>C/c(x1,y1,x2,y2,x,y)+</td>
                            <td>从当前位置绘制三次贝塞尔曲线到指定位置</td>
                        </tr>
                        <tr>
                            <td>S/s(x2,y2,x,y)+</td>
                            <td>从当前位置光滑绘制三次贝塞尔曲线到指定位置</td>
                        </tr>
                        <tr>
                            <td>Q/q(x1,y1,x,y)+</td>
                            <td>从当前位置绘制二次贝塞尔曲线到指定位置</td>
                        </tr>
                        <tr>
                            <td>T/t(x,y)+</td>
                            <td>从当前位置光滑绘制二次贝塞尔曲线到指定位置</td>
                        </tr>
                        <tr>
                            <td>A/a(rx[x半轴长],ry,xr[弧线所在椭圆的长轴角度],laf[是否选择弧线较长的那一段弧],sf[是否选择逆时针方向的那一段弧],x[终点位置],y)</td>
                            <td>从当前位置绘制弧线到指定位置</td>
                        </tr>
                    </table>
                </li>
            </ul>
            <ul>
                <li>命令的基本规律：</li>
                <li>区分大小写：大写表示坐标参数为绝对位置，小写则为相对位置</li>
                <li>最后的参数表示最终要到达的位置</li>
                <li>上一个命令结束的位置就是下一个命令开始的位置</li>
                <li>命令可以重复参数表示重复执行同一条命令</li>
                <li><a href="http://graphic.duapp.com/path-editor.html" target="_blank">graphic.duapp.com/path-editor.html</a></li>
            </ul>
        </li>
        <br>
        <li>SVG文本
            <ul>
                <li>&lt;text&gt;和&lt;tspan&gt;创建文本
                    <ul>
                        <li>x和y属性 -- 定义标准 <br>dx和dy属性 -- 字形偏移 <br>style属性 -- 设置样式</li>
                        <li>
                            <svg xmlns="http://www.w3.org/2000/svg" width="800" height="200">
                                <defs>
                                    <pattern id="grid" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
                                        <path stroke="#f0f0f0" fill="none" d="M0,0H20V20"></path>
                                    </pattern>
                                </defs>
                                <rect x="0" y="0" fill="url(#grid)" width="800" height="200"></rect>

                                <text id="sintext" x="100" y="100" dx="20 20 20 20" dy="20 20 20 20 20"
                                      style="font-size: 12px">ABCDEFGHIJKLMNOPQRSTUVWXYZ</text>
                                <path d="M100,0V200M0,100H200" stroke="red"></path>
                            </svg>
                        </li>
                        <br>
                        <li>tspan,dy属性是能往下传递的</li>
                        <li>
                            <svg xmlns="http://www.w3.org/2000/svg" width="800" height="200">
                                <defs>
                                    <pattern id="grid2" x="0" y="0" width="20" height="20"
                                             patternUnits="userSpaceOnUse">
                                        <path stroke="#f0f0f0" fill="none" d="M0,0H20V20"></path>
                                    </pattern>
                                </defs>
                                <rect x="0" y="0" fill="url(#grid2)" width="800" height="200"></rect>

                                <text x="100" y="100" style="font-size: 50px"><tspan fill="red">AB</tspan><tspan
                                        stroke="green" stroke-width="2" fill="none">CDE
                                </tspan>
                                </text>
                                <path d="M100,0V200M0,100H200" stroke="red"></path>
                            </svg>
                        </li>
                        <br>
                        <li>
                            <svg xmlns="http://www.w3.org/2000/svg" width="800" height="200">
                                <defs>
                                    <pattern id="grid3" x="0" y="0" width="20" height="20"
                                             patternUnits="userSpaceOnUse">
                                        <path stroke="#f0f0f0" fill="none" d="M0,0H20V20"></path>
                                    </pattern>
                                </defs>
                                <rect x="0" y="0" fill="url(#grid3)" width="800" height="200"></rect>

                                <text x="100" y="100" id="sintext2" style="font-size: 12px"></text>
                                <path d="M100,0V200M0,100H200" stroke="red"></path>
                            </svg>
                        </li>
                    </ul>
                </li>
                <li>垂直居中问题
                    <ul>
                        <li>text-anchor - 水平居中属性</li>
                        <li><a href="jsBin.html" target="_blank">dominant-baseline属性</a></li>
                        <li><a href="jsBin2.html" target="_blank">自己模拟</a></li>
                    </ul>
                </li>
                <li>&lt;textPath&gt;让文本在指定路径上排列(属性x,y,dx,dy)
                    <ul>
                        <li>
                            <svg xmlns="http://www.w3.org/2000/svg" width="800" height="300">
                                <text x="0" y="0" style="font-size: 18px">
                                    <textPath xlink:href="#path1">这个文字先上去，又下来了</textPath>
                                </text>
                                <path id="path1" d="M100 200 Q 200 100 300 200" stroke="red" fill="none"></path>
                            </svg>
                        </li>
                        <li>x、text-anchor和startOffset属性：确定排列起始位置</li>
                        <li>dx、dy属性：切线和法线方向的偏移</li>
                        <li><a href="textpath.html" target="_blank">演示</a></li>
                        <li>如果要对dy进行修改，把文字拆分成tspan</li>
                    </ul>
                </li>
                <li>脚本控制路径文本(<a href="textpath2.html">示例</a>)
                    <ul>
                        <li>setAttributeNS()方法设置xlinkL:href属性</li>
                        <li>把文本节点替换为&lt;textpath&gt;节点</li>
                    </ul>
                </li>
                <li>&lt;a&gt; - 超链接
                    <ul>
                        <li>可以添加到任意的图形上</li>
                        <li>xlink：href指定连接地址</li>
                        <li>xlink：title指定连接提示</li>
                        <li>target指定打开目标</li>
                    </ul>
                </li>
            </ul>
        </li>
        <br>
        <li>图形的引用、裁切和蒙版
            <ul>
                <li>&lt;use&gt;标签创建图形引用</li>
                <li>&lt;clip&gt;标签裁切图形</li>
                <li>&lt;mask&gt;标签创建蒙版</li>
            </ul>
        </li>
    </ul>
</body>
<script>
    // x = [20,20,20...]
    // y = s * sin(w * x + t)
    var NS = 'http://www.w3.org/2000/svg';
    var text = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
    var n = text.length;
    var x = [];
    var y = null;
    var i = n;
    var s = 80;
    var w = 0.02;
    var t = 0;
    var sintext = document.getElementById('sintext');
    var sintext2 = document.getElementById('sintext2');
    while(i--) {
        x.push(10);
        var tspan = document.createElementNS(NS, 'tspan');
        tspan.textContent = text[n - i - 1];
        sintext2.appendChild(tspan);
        var h = Math.round(360 / 26 * i);
        tspan.setAttribute('fill', 'hsl(' + h + ', 100%, 80%)');
    }
    function arrange(t) {
        y = [];
        var ly = 0, cy;
        for(i = 0; i < n; ++i) {
            cy = -s * Math.sin( w * i * 20 + t);
            y.push(cy - ly);
            ly = cy;
        }
        // console.table(y);
    }
    function render() {
        sintext.setAttribute('dx', x.join(' '));
        sintext2.setAttribute('dx', x.join(' '));
        sintext.setAttribute('dy', y.join(' '));
        sintext2.setAttribute('dy', y.join(' '));
    }
    function frame() {
        t += 0.01;
        arrange(t);
        render();
        requestAnimationFrame(frame);
    }
    frame();
</script>
</html>